package com.oj.service.impl;

import com.oj.entity.OnlineUser;
import com.oj.entity.User;
import com.oj.mapper.UserMapper;
import com.oj.service.UserService;
import com.oj.util.IpUtil;
import com.oj.util.OnlineUserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
public class UserServiceImpl implements UserService {
    public static final String COOKIE_NAME_TOKEN = "cookieOnlineJudgeToken";
    public static final String COOKIE_NAME_USERNAME = "cookieOnlineJudgeUsername";
    /**
     * token过期时间，2天
     */
    public static final int TOKEN_EXPIRE = 3600 * 24 * 2;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String getTokenCookieName() {
        return COOKIE_NAME_TOKEN;
    }

    @Override
    public String getUsernameCookieName() {
        return COOKIE_NAME_USERNAME;
    }

    @Override
    @Transactional
    public List<User> query() {
        return userMapper.queryList();
    }

    @Override
    @Transactional
    public List<User> topUsers() {
        return userMapper.topUsers();
    }

    @Override
    public Integer getUserRank(User user) {return userMapper.getUserRank(user) + 1;}

    @Override
    @Transactional
    public User query(String username) {
        return userMapper.query(username);
    }

    @Override
    public boolean update(User user) {
        return userMapper.update(user);
    }

    @Override
    public boolean login(HttpServletRequest request, HttpServletResponse response, String username, String password) {
        User user = query(username);
        if(user != null){
            if (user.getPassword().equals(password)) {
                OnlineUserUtil.userOnline(user.getUsername());

                request.getSession().setAttribute("session_username", user.getUsername());
                request.getSession().setAttribute("session_user_rate", user.getRate());

                String avatar_url = user.getAvatar();
                if (avatar_url == null || "N".equals(avatar_url) || "".equals(avatar_url)) {
                    avatar_url = "/img/photo.png";
                } else {
                    if ("Y".equals(avatar_url)) {
                        avatar_url = "/upload/userphoto/" + user.getUsername() + "/photo.png";
                    }
                }
                user.setAvatar(avatar_url);
                request.getSession().setAttribute("session_user_avatar_url", avatar_url);

                String token = UUID.randomUUID().toString().replace("-", "");
                addUserCookie(response, token, user);
                user.setToken(token);
                SimpleDateFormat simpleDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                user.setLastlogin(Timestamp.valueOf(simpleDate.format(new Date())));
                user.setLastaccesstime(Timestamp.valueOf(simpleDate.format(new Date())));
                user.setIp(IpUtil.getIpAddr(request));
                if (user.getCity() == null || user.getCity().length() == 0) {
                    user.setCity(IpUtil.IpSearcherCity(user.getIp()));
                }
                log.info(username + " login from " + user.getIp() + " " + IpUtil.IpSearcherCity(user.getIp()));
                return update(user);
            }
        }

        return false;
    }

    @Override
    public void logout(HttpServletRequest request, HttpServletResponse response) {
        try {
            String username = request.getSession().getAttribute("session_username").toString();
            if (username != null) {
                log.info(username + " logout");
                User user = query(username);
                if (user != null) {
                    user.setToken("");
                    OnlineUser ou = OnlineUserUtil.getUser(username);
                    if (ou != null) {
                        user.setLastaccesstime(ou.getLastAccessTime());
                        OnlineUserUtil.userOffline(username);
                    }
                    update(user);
                }
            }

            request.getSession().removeAttribute("session_username");
            delUserCookie(response);
        } catch (Exception e) {
            // TODO: handle exception
            log.error("logout exception.");
            return;
        }
        return;
    }

    @Override
    public String register(HttpServletRequest request, HttpServletResponse response, User user) {
        if (userMapper.query(user.getUsername()) != null) {
            return "此用户名已经注册";
        }
        if (userMapper.queryMail(user.getEmail()) != null) {
            return "此邮箱已经注册";
        }

        Date dt = new Date();
        SimpleDateFormat simpleDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        user.setBirthday(Timestamp.valueOf(simpleDate.format(dt)));
        user.setRegdate(Timestamp.valueOf(simpleDate.format(dt)));
        user.setLastlogin(Timestamp.valueOf(simpleDate.format(dt)));
        user.setLastaccesstime(Timestamp.valueOf(simpleDate.format(dt)));
        Integer id = userMapper.insertUser(user);
        if (id != 1) {
            return "注册用户失败";
        }

        request.getSession().setAttribute("session_user_avatar_url", "/img/photo.png");
        request.getSession().setAttribute("session_username", user.getUsername());
        request.getSession().setAttribute("session_user_rate", 0);

        String token = UUID.randomUUID().toString().replace("-", "");
        addUserCookie(response, token, user);
        user.setToken(token);

        /* 刷新位置 */
        user.setIp(IpUtil.getIpAddr(request));
        if (user.getCity() == null || user.getCity().length() == 0) {
            user.setCity(IpUtil.IpSearcherCity(user.getIp()));
        }
        if (update(user) != true) {
            return "更新Token失败";
        }

        log.info(user.getUsername() + " register");
        return "SUCCESS";
    }

    private void delUserCookie(HttpServletResponse response) {
        Cookie cookie = new Cookie(COOKIE_NAME_TOKEN, null);
        cookie.setMaxAge(0);
        cookie.setPath("/");
        response.addCookie(cookie);

        Cookie cookieUser = new Cookie(COOKIE_NAME_USERNAME, null);
        cookieUser.setMaxAge(0);
        cookieUser.setPath("/");
        response.addCookie(cookieUser);
    }

    private void addUserCookie(HttpServletResponse response, String token, User user) {
        Cookie cookie = new Cookie(COOKIE_NAME_TOKEN, token);
        cookie.setMaxAge(TOKEN_EXPIRE);
        cookie.setPath("/");
        response.addCookie(cookie);

        Cookie cookieUser = new Cookie(COOKIE_NAME_USERNAME, user.getUsername());
        cookieUser.setMaxAge(TOKEN_EXPIRE);
        cookieUser.setPath("/");
        response.addCookie(cookieUser);
    }

    @Override
    public User getUserBySession(HttpServletRequest request) {
        try {
            String username = request.getSession().getAttribute("session_username").toString();
            if (username == null) {
                return null;
            }
            return userMapper.query(username);
        } catch (Exception e) {
            return null;
        }
    }
}
